﻿#include <iostream>
#include <memory>
#include <future>
#include <vector>

#include <algorithm>
#include <string>

using namespace std;

auto PointerSizeTest() -> void;

class A : public std::enable_shared_from_this<A> {
public:
    explicit A(const std::string &data) {
        m_data1 = std::make_unique<std::string>(data);
        m_data2 = std::make_shared<std::string>(data);
    }

    explicit A(const char *data, int datalen) {
        m_data1 = std::make_unique<std::string>(data, datalen);
        m_data2 = std::make_shared<std::string>(data, datalen);
    }

    std::unique_ptr<std::string> &getData1() {
        return m_data1;
    }

    std::shared_ptr<std::string> getData2() {
        return m_data2;
    }

    void TestSharedFromThis() {
        std::thread([](const std::shared_ptr<A> &spA) -> void {
            std::this_thread::sleep_for(std::chrono::seconds(10));
            spA->getData2()->resize(10, '\0');
            std::cout << "test3 in thread.\n";
        }, shared_from_this()).detach();
    }

protected:

private:
    std::unique_ptr<std::string> m_data1{nullptr};
    std::shared_ptr<std::string> m_data2{nullptr};
};

auto create_unique_ptr(const std::string &ss) -> std::unique_ptr<A> {
    return std::unique_ptr<A>(new A(ss));
}

int main(int argc, char *argv[]) {
    std::vector<std::unique_ptr<A>> vecs;
    for (auto i = 0; i < 10; ++i) {
        auto ptr = create_unique_ptr(std::to_string(i));
        vecs.emplace_back(std::move(ptr));
    }
    std::shared_ptr<A> aaa{new A{""}};
    std::weak_ptr<A> aa = aaa;
    aa.lock();
    for (auto &it: vecs) {
        std::cout << *(it->getData1()) << std::endl;
    }
    PointerSizeTest();

// std::string s1{ "1234567890" };

// {
// 	auto a{ std::make_shared<A>(s1) };
// 	auto& data1 = a->getData1();
// 	auto&& data2 = a->getData2();
// 	std::weak_ptr<std::string> wp_data2 = data2;
// 	a->TestSharedFromThis();
// 	std::cout << "test1." << std::endl;
// }
// std::cout << "test2." << std::endl;

// getchar();
    return 0;
}

auto PointerSizeTest() -> void {
    std::cout << "unique_ptr: size = " << sizeof(std::unique_ptr<int>) << std::endl;
    std::cout << "shared_ptr: size =" << sizeof(std::shared_ptr<int>) << std::endl;
    std::cout << "weak_ptr: size =" << sizeof(std::weak_ptr<int>) << std::endl;
}
